iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
Software Development

六邊形戰士程式設計系列 第 29

D29 - 如何利用各種範式校閱、整合、優化程式 ?

  • 分享至 

  • xImage
  •  

不知道大家工作上是不是也常遇到過這些問題 ?

  • 這段程式碼太長太亂,讀起來好吃力
  • 這段程式碼之前 .. 好像 .. 有寫過但是不知道去哪裡找 ?
  • 功能小改一下,但不知道改下去會不會導致其他功能壞掉
  • 本來應該要寫單元測試的,但是程式寫完才發現測試不知道該怎麼測 ...
  • 明明資料庫、CPU、記憶體資源都沒吃滿,怎麼效能這麼差
  • 明明做的事情很簡單,怎麼消耗了好多計算資源

這些小問題隨著天長日久,累積起來就會像是滾雪球一樣滾出大問題。所以最好的方法就是在察覺問題的時候,就爭取馬上著手解決它。工作到現在我會覺得

每一個讓你難受的點,都是可以學習改進的機會

這段程式碼太長太亂,讀起來好吃力

函數式

  • 觀察整個流程,把每一段流程取名字,如果一段流程能取用一個簡單的名字表示,通常就代表它適合抽出去變成另一個函式,例如:
    • turnLeft 適合單獨抽出去
    • turnLeftAndTurRightAndTakeTwoStep 不要寫這種函式!
  • 有些操作實在是太常見太重複了,尤其是資料結構的操作、錯誤處理、非同步事件的處理,多認識並合理使用這些工具函式可以大幅降低程式碼複雜度
    • 假設有一個二維陣列,我們要把它變成一維陣列,手刻會長這樣
      let oldArray = [[...], [...], ...]
      let newArray = []
      for(row of oldArray){
          for(item of row){
              newArray.push(item)
          }
      }
      
    • 利用 flatten 這個工具就可以非常簡單的達成目標
      const oldArray = [[...], [...], ...]
      const newArray = flatten(oldArray)
      

切面導向

  • 利用函數式程式設計的技巧把流程命名後,如果有些流程滿足兩個條件就可以抽出去變成一個切面
    • 這個流程不式目前流程的主要流程,只是輔助功能
    • 這個流程會出現在很多不同的主要流程之中
  • 例如驗證、監控、效能測試

這段程式碼之前 .. 好像 .. 有寫過但是不知道去哪裡找 ?

物件導向

  • 觀察專案的資料夾結構,嘗試從專案層面上作分類,不同類型的專案有不同的設計方式,可以多看看找找架構設計的教學,以後端來說常常會有
    • controller
    • service
    • model
    • repository
  • 每個層級往下都可以視需要再細分,但切忌過度設計,例如 model 還可以往下分
    • po
    • dto
    • entity
    • vo
    • ...
  • 設計的時候可以留下一些文件,重要的是務必要確保團隊成員對這些分類有共識,不然過一陣子又亂掉了
  • 依照這些分類方式對程式碼做封裝,把相關的資料跟方法包在一起,這樣一來只要找到目標類別,就能找到所有相關的功能

功能小改一下,但不知道改下去會不會導致其他功能壞掉

函數式

  • 在進行資料操作時,盡量保持不可變動性(immutability),可以確保不會計算到一半被其他流程給陰了
  • 盡量保持型別安全,型別設計越是注重細節,越容易在開發階段就發現型別錯誤
  • 即使是弱型別
  • 雖然說型別設計通常越細緻越好,但是也會同時導致開發成本上升,如何取捨是個問題

物件導向

  • 良好的物件導向設計遵守 SOLID 原則,程式碼的小改動常常可以限制在一個檔案內
  • 然而遵守規則同樣需要付出額外的成本,同樣需要進行取捨,以單一職責原則(SRP)來說
    • 我們需要一到多個 PO 用來和資料庫互動
    • 我們需要一到多個 DTO 來和不同客戶端互動
    • 我們需要一個 Entity 作為以上 PO/DTO 轉換的核心
  • 如果我的資料庫、資料處理、請求回應都是同一個資料型別,是不是就可以不遵守單一職責原則了呢?
  • 有時候過度遵守設計原則同樣是過度設計
  • 所以再說一次,不要過度設計

本來應該要寫單元測試的,但是程式寫完才發現不知道該怎麼測 ...

函數式

  • 單元測試的目標是主要程式邏輯,不應該包含外部服務,以及他們可能造成的副作用
  • 通常難的是如何把程式中的副作用主要程式邏輯切割開來
  • 只要副作用都被剝離到主要流程,變成純函式,相信我,超級好測的!

物件導向

  • 只要遵守依賴反轉原則,我們就可以實作簡單的虛假測試用介面來測試物件行為

明明資料庫、CPU、記憶體資源都沒吃滿,怎麼效能這麼差

響應式程式設計

  • 把佔據大量資源的任務變成可觀察的資料流
  • 篩掉重複的、沒意義的事件
  • 現在應用層面的程式效能通常受限於外部資源讀寫,因此盡量依賴前期的資料流處理,減少外部資源讀寫
  • 利用 coroutine / suspend / async await / concurrent ...設計妥善利用資源

明明做的事情很簡單,怎麼消耗了好多計算資源

程序式/結構式

雖然現在大部分時候計算資源式過剩的,但有時候抽象化太過頭,還是難免會有效能問題,這時候就得先找出哪些部分是瓶頸,再把這部分用程序式/結構式的寫作方式,用最簡單的硬體的執行方式重寫一遍


上一篇
D28 - MMORPG事件處理問題 多語言篇
下一篇
D30 - 總結
系列文
六邊形戰士程式設計30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言